use std::collections::HashMap;

struct Vocab {
    content: [char; 16],
    idxs: HashMap<char, usize>,
}

impl Vocab {
    fn new() -> Self {
        let content = [
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
        ];
        let idxs = HashMap::from([
            ('0', 0),
            ('1', 1),
            ('2', 2),
            ('3', 3),
            ('4', 4),
            ('5', 5),
            ('6', 6),
            ('7', 7),
            ('8', 8),
            ('9', 9),
            ('a', 10),
            ('b', 11),
            ('c', 12),
            ('d', 13),
            ('e', 14),
            ('f', 15),
        ]);
        Vocab { content, idxs }
    }

    fn char_to_value(&self, c: char) -> usize {
        *self.idxs.get(&c).unwrap()
    }

    fn value_to_char(&self, value: usize) -> char {
        self.content[value]
    }
}

pub fn convert_base(num_str: &str, to_base: u32) -> String {
    let (num, from_base_str) = num_str.strip_suffix(')').unwrap().split_once('(').unwrap();
    let from_base = from_base_str.parse::<u32>().unwrap();
    if from_base > 16 || from_base < 2 || to_base > 16 || to_base < 2 {
        panic!("This function only supports bases up to 16, down to 2.");
    }

    let vocab = Vocab::new();

    // Convert from the original base to 10
    let decimal_value = num
        .to_lowercase()
        .chars()
        .rev()
        .enumerate()
        .map(|(i, c)| vocab.char_to_value(c) * from_base.pow(i as u32) as usize)
        .sum::<usize>();

    // Convert from decimal to the target base
    let mut result = String::new();
    let mut value = decimal_value;
    while value > 0 {
        let remainder = value % to_base as usize;
        result.push(vocab.value_to_char(remainder));
        value /= to_base as usize;
    }

    if result.is_empty() {
        result.push('0');
    }

    result.chars().rev().collect()
}

// 思路:
// 定义词表进行迅速转换
// 通过 10 进制 进行中转
